#ifndef __BLOCK_QUEUE_H_
#define __BLOCK_QUEUE_H_

#include <string>
#include <deque>
#include "Mutex.h"

#include "Condition.h"

#ifndef MAX_BLOCK_SIZE
#define MAX_BLOCK_SIZE 2048
#endif

namespace BASE{
	class NameQueue{
		public:
			NameQueue(const std::string _name, int _maxSize):queueName(_name),maxSize(_maxSize){

			}

			const std::string & getQueueName(){
				return queueName;
			}

			void setMaxSize(int _maxSize){
				maxSize = _maxSize;
			}

			int getMaxSize() {
				return maxSize;
			}

			virtual int size(){
				return 0;
			}
		protected:
			std::string queueName;
			int			maxSize;
			
	};

	template<typename T>
	class BlockQueue : public NameQueue{
		public:
			BlockQueue(const std::string& _name, int _maxSize = MAX_BLOCK_SIZE):NameQueue(_name, _maxSize){

			}

			~BlockQueue(){

			}

			bool put(const T & t){
				Lock lock(mutex);
				if (blockQueue.size() > MAX_BLOCK_SIZE){
					return false;
				}
				blockQueue.push_back(t);
				cond.notify();
				return true;
			}

			bool get(T& t, int ms){
				Lock lock(mutex);
				if (blockQueue.empty()){
					cond.wait(mutex, ms);
				}
				if (blockQueue.empty()){
					return false;
				}
				t = blockQueue.front();
				blockQueue.pop_front();
				return true;
			}

			bool get(T& t) {
				Lock lock(mutex);
				while (blockQueue.empty() && maxSize > 0){
					cond.wait(mutex);
				}
				if (blockQueue.empty()){
					return false;
				}
				t = blockQueue.front();
				blockQueue.pop_front();
				return true;
			}

			void clear(){
				Lock lock(mutex);
				blockQueue.clear();
			}

			bool isEmpty(){
				Lock lock(mutex);
				return blockQueue.empty();
			}

			void stop(){
				Lock lock(mutex);
				maxSize = 0;
				cond.notifyAll();
			}

			int size(){
				Lock lock(mutex);
				return blockQueue.size();
			}
		private:
			Mutex mutex;
			std::deque<T> blockQueue;
			Condition cond;

	};
}

#endif

